package cn.itrip.auth.service;

import cn.itrip.beans.pojo.ItripUser;
import cn.itrip.common.MD5;
import cn.itrip.common.RedisAPI;
import com.alibaba.fastjson.JSON;
import nl.bitwalker.useragentutils.UserAgent;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * @author 瑾
 */
@Service("tokenService")
public class TokenServiceImpl implements  TokenService {
    @Resource(name = "redisAPI")
    private RedisAPI redisAPI;

    /**
     * 生成Token
     *  需要生成的内容格式： pc-userCode-userId-createDate-rondem[6位随机数]
     * @return
     * @throws Exception
     */
    @Override
    public String generateToken(String userAgent, ItripUser user) throws Exception {
      //自重生成的token字符串
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("token:");
        // Agent --代理
        //工具类--获取设备类型
        UserAgent agent = UserAgent.parseUserAgentString(userAgent);
        //1 获取操作系统，然后判断是否移动的设备
        //true 代表是手机设备
        boolean flag = agent.getOperatingSystem().isMobileDevice();
        if(flag){
            stringBuilder.append("MOBLE-");
        }else {
            stringBuilder.append("PC-");
        }
        //2 拼接token内容
        stringBuilder.append(MD5.getMd5(user.getUserCode(),32)+"-");
        stringBuilder.append(user.getId().toString()+"-");
        stringBuilder.append(new SimpleDateFormat("yyyyMMddHHmmsss").format(new Date())+"-");
        stringBuilder.append(MD5.getMd5(userAgent,6));
        System.out.println("控制台输出token为："+stringBuilder.toString());
        return stringBuilder.toString();
    }

    /**
     * 保存用户的Token信息
     *  不同设备，token的会话期是不一样的，手机两个小时，PC10分钟
     * @throws Exception
     */
    @Override
    public void saveToken(String token,ItripUser user) throws Exception {
        //判断它是手机端还是PC端
        if(token.startsWith("token:PC-")){
            redisAPI.set(token,2*60*60, JSON.toJSONString(user));
        }else {
            //119.7min
            redisAPI.set(token,JSON.toJSONString(user));
        }


    }
    /**
     * 验证token的有效性
     * @param userAgent   为了保证每一个用户都是用同一个设备访问
     * @param token
     */
    @Override
    public boolean validate(String userAgent, String token) {
        System.out.println("--验证时的userAgen为："+userAgent);
        //如果 reisAPI存在这个key，代表这个token存在
        if(!redisAPI.exist(token)){
            return false;
        }else {
            //该token存在 --  继续判断
            //验证该token是不是表示是上一次的浏览器生成的
         String   agentMD5= token.split("-")[4];

         //与传入的userAgent比对，是否与上一次的agentMD5相同
            if(!MD5.getMd5(userAgent,6).equals(agentMD5)){
                return false;
            }else {
                //是否需要判断token的有效期， 答 不用 因为pc有效期过了redis会自动删除
                return true;
            }
        }


    }


    /**
     * 删除token
     * @param token
     */
    @Override
    public void deleteToken(String token) {
        redisAPI.delete(token);
    }




    private long protectedTime=30*60; //置换时间--30min
    private int lateTimes = 2*60;//给老token的延迟时期
    /**
     * 新老token置换  //1验证 2生 成新token 3 延长维护老token
     * 1 生成新的token
     *  2 老token不能删除 让他继续存在
     *   3 留出新旧过度的时间
     * @param userAgent
     * @param token
     * @return  新的token
     */
    @Override
    public String reloadToken(String userAgent, String token) throws Exception {
    /*
                 user:
                 生成的时候要传user对象
                从reids里面取出来的user对象序列化之后的user字符串

                 */
        //1 验证token是否有效
        if(!redisAPI.exist(token)){
            throw  new Exception("token无效");
        }else {
            //2
    /*
        能不能置换 因为他有保护期30min 可以减轻服务器压力
            检查token的生成时间和当前时间有没有超过我的置换的保护期时间
                当前时间-token生成时间>30min? 可以置换   否则不可以置换
              */
        //老token的时间
            Date  tokenTime = new SimpleDateFormat("yyyyMMddHHmmss").parse(token.split("-")[3]);
            //当前时间-老token时间的差
            long resultTime = Calendar.getInstance().getTimeInMillis()-tokenTime.getTime();
            System.out.println("--当前时间--"+Calendar.getInstance().getTimeInMillis());
            System.out.println("---老token时间--"+tokenTime.getTime());
            System.out.println("---时间差---"+resultTime/1000);
            System.out.println("--置换保护期---"+protectedTime);
            if(resultTime/1000<protectedTime){
                long syTime = protectedTime-(resultTime/1000);
                throw  new  Exception("置换保护期内不可以置换，你当前剩余时间"+syTime);
            }else {

                //3 进行置换  --反序列化  获得新token
                        String user =redisAPI.get(token);
                ItripUser itripUser = JSON.parseObject(redisAPI.get(token),ItripUser.class);
                        String newToken =null;
                        newToken = this.generateToken(userAgent,itripUser);

                //4 老的token延迟过期
                redisAPI.set(token,lateTimes,user);

                //5  将新token存储到redis里面
                this.saveToken(newToken,itripUser);
                return  newToken;



            }


        }


    }

}
